www.gusucode.com > 串口测试程序,用于调试rs485接口 串口通信的程序 > 串口测试程序,用于调试rs485接口 串口通信的程序/commtest/Text2.cpp

    #include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/select.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include "MyCom.h"
#include <termios.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/file.h>	/* flock(int fd,int operation)函数	*/
using namespace std;
const char *MyCom::Serial_Ctl_No[MAX_COMS] =
                                                       {
                                                       	        "/dev/wfet1000com0",
                                                       	        "/dev/wfet1000com1",
                                                       	        "/dev/wfet1000com2",
                                                       	        "/dev/nothing4",
                                                       	        "/dev/nothing5",
                                                       	        "/dev/nothing6"
                                                       	};
MyCom::MyCom() {
	if(!CreateSem( COM2 ))
	{
	}
}
MyCom::MyCom(enum COM_NO com)
{	
	if(!CreateSem( com ))
	{
	}
}
MyCom::MyCom(BYTE com)
{
	enum COM_NO com_no;
	AttachComNo( com , com_no);
	if(!CreateSem( com_no ))
	{
	}
}

bool MyCom::CreateSem(enum COM_NO com)
{
	union semun sem_union;
	sem_id = semget( (key_t)(SEM_KEY_COM + com), 1, 0666 | IPC_CREAT );
	cur_serial_num = com;
	serial_ctrl_no = 0;

	if( !AttachSem( 0 ) )
	     return false;
	if(com_buf[0] == 1 || com_buf[0] == 2 || com_buf[0] == 3)
	{//串行口的读写控制1:自动;2、3、非自动;2:读、3:写。表示串行口的信号量已初始化
	        m_port_status = com_buf[0];
		return true;
	}
	com_buf[0]    = 1;
	m_port_status = 1; //系统默认为自动收发
	
	sem_union.val=1;
	if(semctl(sem_id, 0, SETVAL, sem_union )==-1) {
		return false;
	}
	return true;	
}


bool MyCom::OpenCtrl()
{
//	if( m_port_status == com_buf[0] ) return true;//系统的收发控制状态一致、不用再控制
	if( serial_ctrl_no <= 0)
	{
		serial_ctrl_no = open(Serial_Ctl_No[ cur_serial_num ], O_WRONLY | O_NOCTTY);
	}

	return (serial_ctrl_no > 0)? true : false;
}

bool MyCom::CloseCtrl()
{
  if (serial_ctrl_no > 0) 
  {
  	close(serial_ctrl_no);
  	serial_ctrl_no = 0;
  }
  return true;
}
bool MyCom::SetPortState(enum PORT_STATE m_status)//TRUE 表示发送, FALSE 为接收
{
	if( m_port_status == com_buf[0] ) return true;//系统的收发控制状态一致、不用再控制
	OpenCtrl();
	unsigned char str[2];
	switch(m_status)
	{
	case STATUS_READ:
		str[0] = 0x00;
		str[1] = 0x00;
		break;
	case STATUS_WRITE:
		str[0] = 0x01;
		str[1] = 0x00;
		break;	
	case STATUS_AUTO:
	default:
		str[0] = 0x00;
		str[1] = 0x01;
		break;
	}
	
	if(serial_ctrl_no <= 0) return false;
	if (write(serial_ctrl_no,str,2) <0 )
	{
		CloseCtrl();
		return false;
	}
	CloseCtrl();
	com_buf[0]    = (BYTE)m_status;
	m_port_status = com_buf[0];
	return true;
}
bool MyCom::AttachSem(int flag)
{
	com_id=shmget( (key_t)MEM_KEY_COM + cur_serial_num, sizeof(BYTE), 0666 | IPC_CREAT ); 
	if ( com_id ==-1 ) {
		return false;
	}
	
	com_addr = shmat(com_id, NULL, flag );
	
	if (com_addr == (void *)-1 ) {
		return false;
	}	
	com_buf = (BYTE *) com_addr;
	return true;
}

void MyCom::Init_Serial(METERCOMPARA com_para)
{
	switch( (int)com_para.baudrate ) {//
		case 1:
			cur_baudrate = B300;
			break;
		case 2:
			cur_baudrate = B600;
			break;
		case 4:
			cur_baudrate = B1200;
			break;
		case 8:
			cur_baudrate = B2400;
			break;
		case 16:
			cur_baudrate = B4800;
			break;
		case 32:
			cur_baudrate = B9600;
			break;
		default:
			cur_baudrate = B9600;
			break;
	}
	switch( (int)com_para.bytesize ) {//COM_BYTESIZE5 = 5,COM_BYTESIZE6 = 6,COM_BYTESIZE7 = 7,COM_BYTESIZE8 = 8
		case 5:
			cur_bytesize = COM_BYTESIZE5 ;
			break;
		case 6:
			cur_bytesize = COM_BYTESIZE6 ;
			break;
		case 7:
			cur_bytesize = COM_BYTESIZE7 ;
			break;
		case 8:
			cur_bytesize = COM_BYTESIZE8 ;
			break;
		default:
			cur_bytesize = COM_BYTESIZE8 ;
		break;
	}
	switch( (int)com_para.parity ) {// PARITY_ODD=0, PARITY_EVEN=1, PARITY_NONE=2
		case 0:
			cur_parity = PARITY_NONE;
			break;
		case 1:
			cur_parity = PARITY_EVEN;
			break;
		case 2:
			cur_parity = PARITY_ODD;
			break;
		default:
			cur_parity = PARITY_EVEN;
		break;
	}
	
	switch( (int)com_para.stopbits ) {
		case 0:
		       cur_stopbits = COM_STOPBITS1;
		       break;
		case 1:
		       cur_stopbits = COM_STOPBITS15;
		       break;
		case 2:
		       cur_stopbits = COM_STOPBITS2;
		default:
		       cur_stopbits = COM_STOPBITS1;
		break;
	}
	
	cur_sync_mode = COM_BLOCK ;
	//SerialCom::serial_sync_mode(COM_BLOCK);
}

bool MyCom::sem_serial_open() {
	if(! sem_P()) {
		return false;
	}
	
	if(!serial_open()) {
//		 sem_V(); 
		 sem_serial_close();
		 return false;
	}
//	OpenCtrl();
	return true;
}

void MyCom::sem_serial_close() {
//	CloseCtrl();
	serial_close() ;
	sem_V();
}

bool MyCom::wait_for_response(int sec_time)
{
    	static fd_set readfs;
     	static struct timeval timeout;

    	timeout.tv_usec = 0;
    	timeout.tv_sec  = sec_time;  /* 设定超时时间为sec_time秒	*/
    			
//	SetPortState( STATUS_READ );  //设置为读状态

	FD_ZERO(&readfs);
    	FD_SET(serial_fd, &readfs);  		
	
	/* 等待数据返回并判断是否超时 */
    	if (select(serial_fd+1, &readfs, NULL, NULL, &timeout) <= 0) {
		return false;
        }	
	/* 读句柄集合里是否是fd句柄来数据 */
	if (FD_ISSET(serial_fd, &readfs) <= 0) {
		tcflush(serial_fd, TCIOFLUSH);
		return false;
	}
	
	return true;
}
bool MyCom::change_port(enum COM_NO com)	//改变对象使用端口
{
	SerialCom::change_port( com );
	if(!CreateSem( com ))
	{
		return false;
	}
	return true;
}

//信号量P操作
bool MyCom::sem_P() {
	struct sembuf sem_b;
	
	if( sem_id==-1 ) {
		return false;
	}
	
	sem_b.sem_num = 0;
	sem_b.sem_op = -1; /*p()*/
	sem_b.sem_flg = SEM_UNDO;
	
	if( semop(sem_id, &sem_b, 1) == -1 ) {
		return false;
	}
	return true;
	
}

//信号量V操作
bool MyCom::sem_V() {
	struct sembuf sem_b;
	
	if( sem_id==-1 ) {
		return false;
	}
	
	sem_b.sem_num = 0;
	sem_b.sem_op = 1; /*v()*/
	sem_b.sem_flg = SEM_UNDO;
	
	if( semop(sem_id, &sem_b, 1) == -1 ) {
		return false;
	}
	return true;
}

//销毁信号量对象
void MyCom::DestroySem() {
//	shmctl( com_id, IPC_RMID, 0 );
//        CloseCtrl();
        if (com_addr == (void *) -1 ) {
		return;
	}
	shmdt(com_addr);
//	semctl( sem_id, 0, IPC_RMID);
}


int MyCom::serial_read(unsigned char * buf, int len)
{
	return SerialCom::serial_read( buf, len);
}
int  MyCom::serial_write(unsigned char * buf, int len)
{
	SetPortState( STATUS_WRITE );
	int Len = SerialCom::serial_write( buf, len);
	SetPortState( STATUS_READ );
	return Len;
}
bool MyCom::AttachComNo(BYTE com_no,enum COM_NO &com)
{
	switch(com_no)
	{
		case 0:
		      com = COM1;
		      break;
		case 1:
		      com = COM2;
		      break;
		case 2:
		      com = COM3;
		      break;
		case 3:
		      com = COM4;
		      break;
		case 4:
		      com = COM5;
		      break;
		case 5:
		      com = COM6;
		      break;
		case 6:
		      com = COM7;
		      break;
		case 7:
		      com =  COM8;
		      break;
	        default:
	              com = COM2;
	              return false;
	}
	return true;
}
bool MyCom::change_port(BYTE com)
{
	enum COM_NO com_no;
	if(!AttachComNo( com, com_no))//bool AttachComNo(BYTE com_no,enum COM_NO &com);
	      return false;	      
	return change_port( com_no );
}